package org.springframework.security.web.context.request.async;

import java.io.IOException;
import java.util.concurrent.Callable;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.context.SecurityContext;
import org.springframework.web.context.request.async.WebAsyncManager;
import org.springframework.web.context.request.async.WebAsyncUtils;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * WebAsyncManagerIntegrationFilter 用于将 SecurityContext 集成到 Spring 异步执行机制中的 WebAsyncManager。用来处理异步请求的安全上下文。
 *
 * 提供 {@link SecurityContext}与 Spring Web 的集成
 * {@link WebAsyncManager} 通过使用 {@link SecurityContextCallableProcessingInterceptor#beforeConcurrentHandling(org.springframework.web.context.request.NativeWebRequest, Callable)} 方法
 * 将 {@link SecurityContext} 设置到 {@link Callable} 上
 *
 * @see SecurityContextCallableProcessingInterceptor
 *
 */
public final class WebAsyncManagerIntegrationFilter extends OncePerRequestFilter {

	private static final Object CALLABLE_INTERCEPTOR_KEY = new Object();

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

		// 1、从请求属性上获取所绑定的 WebAsyncManager，如果尚未绑定，先做绑定。
		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		// 2、从 asyncManager 中获取 key 为 CALLABLE_INTERCEPTOR_KEY 的安全上下文多线程处理器 SecurityContextCallableProcessingInterceptor
		SecurityContextCallableProcessingInterceptor securityProcessingInterceptor = (SecurityContextCallableProcessingInterceptor) asyncManager.getCallableInterceptor(CALLABLE_INTERCEPTOR_KEY);

		// 3、如果获取的 securityProcessingInterceptor 为 null，则新建一个 SecurityContextCallableProcessingInterceptor 并绑定 CALLABLE_INTERCEPTOR_KEY 注册到 asyncManager 中。
		if (securityProcessingInterceptor == null) {
			asyncManager.registerCallableInterceptor(CALLABLE_INTERCEPTOR_KEY, new SecurityContextCallableProcessingInterceptor());
		}

		// 4、执行过滤器逻辑
		filterChain.doFilter(request, response);
	}

}
